package ar.com.uade.administradorsiembra.persistencia;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.log4j.Logger;
import ar.com.uade.administradorsiembra.common.AdministradorTransaccional;
import ar.com.uade.administradorsiembra.common.Transaccion;
import ar.com.uade.administradorsiembra.modelo.Entidad;
import ar.com.uade.administradorsiembra.modelo.exceptions.TransaccionException;

public abstract class Mapper <T extends Entidad> {	
	protected final Logger logger;
	protected final AdministradorTransaccional administradorTransaccional;
	protected Transaccion transaccionActual;
	
	public Mapper() {
		this.logger = Logger.getLogger(this.getClass());
		this.administradorTransaccional = AdministradorTransaccional.getInstancia();
	}
	
	public boolean guardarTodos(List<T> instancias, Transaccion transaccion) throws TransaccionException {
		this.transaccionActual = transaccion;
		
		return this.guardarTodos(instancias);
	}
	
	public abstract boolean guardarTodos(List<T> instancias) throws TransaccionException;

	public boolean guardar(T instancia, Transaccion transaccion) throws TransaccionException {
		this.transaccionActual = transaccion;
		
		return this.guardar(instancia);
	}
	
	public abstract boolean guardar(T instancia) throws TransaccionException;
	
	public boolean modificar(T instancia, Transaccion transaccion) throws TransaccionException {
		this.transaccionActual = transaccion;
		
		return this.modificar(instancia);
	}
	
	public abstract boolean modificar(T instancia) throws TransaccionException;
	
	public boolean borrar(T instancia, Transaccion transaccion) throws TransaccionException {
		this.transaccionActual = transaccion;
		
		return this.borrar(instancia);
	}
	
	public abstract boolean borrar(T instancia) throws TransaccionException;
	
	public abstract List<T> buscarTodos();
	
	public abstract T buscarPorId(Integer id);
	
	protected ResultSet executeQuery(String sql, List<Object> parametros, Connection conexion) throws SQLException {	
		this.logger.info("Ejecutando metodo executeQuery para la consulta: " + sql + " y los parametros " + parametros);
		
		ResultSet resultado = null;
		PreparedStatement ps = conexion.prepareStatement(sql);
		int i = 1;
		
		for (Object object : parametros) {
			ps.setObject(i, object);
			i++;
		}
		
		resultado = ps.executeQuery();
		this.logger.info("Consulta ejecutada en forma exitosa.");
				
		return resultado;
	}
	
	protected int executeUpdate(String sql, List<Object> parametros, Connection conexion) throws SQLException {	
		this.logger.info("Ejecutando metodo executeUpdate para la consulta: " + sql + " y los parametros "+ parametros);
		
		int resultado = 0;
		PreparedStatement ps = conexion.prepareStatement(sql);
		int i = 1;
		
		for (Object object : parametros) {
			ps.setObject(i, object);
			i++;
		}
		
		resultado = ps.executeUpdate();	
		this.logger.info("Le ejecucion afecto a " + resultado + " registros");
		
		return resultado;
	}	
}
